<?php

declare (strict_types=1);


namespace addons\Queue\driver;

use think\queue\Job;

class QueueBase
{
    use \addons\Queue\driver\QueueTrait;

    protected string $method = 'handle';

    protected string $queueLogFile;


    public function __construct()
    {
        $shortClassName = basename(str_replace('\\', '/', get_class($this)));
        $this->queueLogFile = 'queue/' . $shortClassName . '.log';
    }

    public function __call(string $name, array $arguments)
    {
        $this->fire(...$arguments);
    }

    /**
     * 写入日志
     * @param string $method
     * @param string $msg
     * @return void
     */
    public function writeLog(string $method, string|int $msg): void
    {
        if (!empty($this->queueLogFile)) {
            $fileName = app()->getRootPath() . 'public/' . $this->queueLogFile;
            file_put_contents($fileName, sprintf("时间：%s\r\n 类：%s\r\n 方法名：%s\r\n 内容：%s\r\n",
                date('Y-m-d H:i:s'),
                static::class,
                $method,
                $msg
            ), FILE_APPEND);
        }
    }

    /**
     * 触发队列任务
     * @param Job $job
     * @param mixed $params
     * @return void
     */
    public function fire(Job $job, mixed $params): void
    {
        try {

            $this->execute($params['action'], $job, $params['data'], $params['retry_num']);
        } catch (\Exception|\Throwable $e) {
            $job->delete();
            $this->writeLog('job', $e->getMessage());
        }
    }

    /**
     * 执行队列
     * @param string $action
     * @param Job $job
     * @param array $request
     * @param int $retryNums
     * @return void
     */
    protected function execute(string $action, Job $job, array $data, int $retryNums): void
    {
        $action = method_exists($this, $action) ? $action : $this->method;
        if (!method_exists($this, $action)) {
            $this->writeLog('execute', '执行方法不存在');
            $job->delete();
        } else {
            if ($this->{$action}($data)) {
                $job->delete();
            } else {
                if ($job->attempts() >= $retryNums) {
                    $job->delete();
                    $this->writeLog('execute', '到达最大重试次数，执行失败：' . json_encode($data));
                } else {
                    $job->release();
                    $this->writeLog('execute', '队列执行失败，重新进入：' . json_encode($data));
                }
            }
        }
    }
}